package jannex.sql.extensions;

import jannex.Jannex;
import jannex.internal.ExceptionFactory;
import jannex.sql.JxConnection;
import jannex.sql.JxResultSet;
import jannex.sql.JxStatement;
import jannex.sql.TypedStatement;

import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;

public class StatementImpl implements JxStatement {

    protected Statement statement;
    protected Jannex jannex;

    public StatementImpl(Statement statement, Jannex jannex) {
        this.statement = statement;
        this.jannex = jannex;
    }

    @Override
    public <E> TypedStatement<E> as(Class<E> elementClass) {
        return new TypedStatementImpl<>(statement, jannex, jannex.getHandler(elementClass));
    }

    @Override
    public JxResultSet getResultSet() {
        try {
            return new ResultSetImpl(statement.getResultSet(), jannex);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void close() {
        try {
            statement.close();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getMaxFieldSize() {
        try {
            return statement.getMaxFieldSize();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void setMaxFieldSize(int max) {
        try {
            statement.setMaxFieldSize(max);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getMaxRows() {
        try {
            return statement.getMaxRows();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void setMaxRows(int max) {
        try {
            statement.setMaxRows(max);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void setEscapeProcessing(boolean enable) {
        try {
            statement.setEscapeProcessing(enable);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getQueryTimeout() {
        try {
            return statement.getQueryTimeout();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void setQueryTimeout(int seconds) {
        try {
            statement.setQueryTimeout(seconds);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void cancel() {
        try {
            statement.cancel();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public SQLWarning getWarnings() {
        try {
            return statement.getWarnings();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void clearWarnings() {
        try {
            statement.clearWarnings();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void setCursorName(String name) {
        try {
            statement.setCursorName(name);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getUpdateCount() {
        try {
            return statement.getUpdateCount();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean getMoreResults() {
        try {
            return statement.getMoreResults();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void setFetchDirection(int direction) {
        try {
            statement.setFetchDirection(direction);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getFetchDirection() {
        try {
            return statement.getFetchDirection();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void setFetchSize(int rows) {
        try {
            statement.setFetchSize(rows);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getFetchSize() {
        try {
            return statement.getFetchSize();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getResultSetConcurrency() {
        try {
            return statement.getResultSetConcurrency();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getResultSetType() {
        try {
            return statement.getResultSetType();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void addBatch(String sql) {
        try {
            statement.addBatch(sql);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void clearBatch() {
        try {
            statement.clearBatch();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int[] executeBatch() {
        try {
            return statement.executeBatch();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public JxConnection getConnection() {
        try {
            return new ConnectionImpl(statement.getConnection(), jannex);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean getMoreResults(int current) {
        try {
            return statement.getMoreResults(current);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public JxResultSet getGeneratedKeys() {
        try {
            return new ResultSetImpl(statement.getGeneratedKeys(), jannex);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public JxResultSet executeQuery(String sql) {
        try {
            return new ResultSetImpl(statement.executeQuery(sql), jannex);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int executeUpdate(String sql) {
        try {
            return statement.executeUpdate(sql);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean execute(String sql) {
        try {
            return statement.execute(sql);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int executeUpdate(String sql, int autoGeneratedKeys) {
        try {
            return statement.executeUpdate(sql, autoGeneratedKeys);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int executeUpdate(String sql, int[] columnIndexes) {
        try {
            return statement.executeUpdate(sql, columnIndexes);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int executeUpdate(String sql, String[] columnNames) {
        try {
            return statement.executeUpdate(sql, columnNames);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean execute(String sql, int autoGeneratedKeys) {
        try {
            return statement.execute(sql, autoGeneratedKeys);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean execute(String sql, int[] columnIndexes) {
        try {
            return statement.execute(sql, columnIndexes);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean execute(String sql, String[] columnNames) {
        try {
            return statement.execute(sql, columnNames);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public int getResultSetHoldability() {
        try {
            return statement.getResultSetHoldability();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean isClosed() {
        try {
            return statement.isClosed();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void setPoolable(boolean poolable) {
        try {
            statement.setPoolable(poolable);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean isPoolable() {
        try {
            return statement.isPoolable();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public void closeOnCompletion() {
        try {
            statement.closeOnCompletion();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean isCloseOnCompletion() {
        try {
            return statement.isCloseOnCompletion();
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T unwrap(Class<T> iface) {
        try {
            if (iface.equals(Statement.class)) {
                return (T) statement;
            }
            return statement.unwrap(iface);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) {
        try {
            return iface.equals(Statement.class) || statement.isWrapperFor(iface);
        } catch (SQLException e) {
            throw ExceptionFactory.make(e);
        }
    }
}
